<?php

namespace service;

use constant\RedisConstant;
use util\RedisTool;
use Webman\RedisQueue\Client;

class TaskService
{
    /**
     * 配置派发设置
     * @param array $args
     * @return string
     */
    public static function setTaskSetting(array $args): string
    {
        try {
            $taskType = $args['taskType'] ?? 'assign'; //任务类型、标识
            $taskSign = $args['taskSign'] ?? '1'; //分派名称、标识、ID
            $allowAssign = $args['allowAssign'] ?? 0; //是否允许分派
            $assignMode = $args['assignMode'] ?? 1; //分派模式 默认4种派发模式 [1：循环派发 2：指定派发 3：比例派发 4：均等派发]
            $assignTime = $args['assignTime'] ?? ''; //派发时间段 08：00-23：00，默认整天
            $assignDuty = $args['assignDuty'] ?? 0; //派发值班开启状态
            $dutyTime = $args['dutyTime'] ?? []; //值班时间段 仅开启生效 ["08:00-12:00","12:00-13:30"]
            $assignNotViewed = $args['assignNotViewed'] ?? 0; //未查看的任务，是否继续派发
            $viewWaitingTime = $args['viewWaitingTime'] ?? 5; //任务派发等待时间，单位分钟,未查看继续派发开启生效
            $assignType = $args['assignType'] ?? 1; //派发形式 [1:企业微信群机器人]
            $sendAssignUrl = $args['sendAssignUrl'] ?? ''; //推送链接 1:企业微信群机器人

            if (!in_array($assignMode, [1, 2, 3, 4])) throw new \Exception('不支持的分派模式');
            if (!in_array($assignType, [1, 2, 3, 4, 5, 6])) throw new \Exception('不支持的派发形式');

            $taskSetting = RedisConstant::TaskPrefix . $taskType . ':task:' . $taskSign;
            $exist = RedisTool::get_exists($taskSetting, 'config');
            $setting = [
                'taskSign' => $taskSign,
                'allowAssign' => $allowAssign,
                'assignMode' => $assignMode,
                'assignTime' => $assignTime,
                'assignDuty' => $assignDuty,
                'dutyTime' => $dutyTime,
                'assignNotViewed' => $assignNotViewed,
                'viewWaitingTime' => $viewWaitingTime,
                'assignType' => $assignType,
                'sendAssignUrl' => $sendAssignUrl,
            ];
            $res = RedisTool::set_forever($taskSetting, $setting, 'config');
            //修改时同步分配队列
            $redisKey = RedisConstant::TaskPrefix . $taskType . ':user:' . RedisConstant::TaskAssignNormal . $taskSign;
            $type = RedisTool::type($redisKey, 'list');
            $userList = [];
            if ($type == 3) $userList = RedisTool::get_lRange($redisKey, 0, -1, 'list');
            elseif ($type == 4) $userList = RedisTool::get_zSet_desc($redisKey, 0, 1, 'list');
            if ($userList) Client::send(RedisConstant::TaskUserList, [
                'name' => RedisConstant::TaskPrefix . $taskType . ':user:',
                'sign' => $taskSign,
                'mode' => $assignMode,
                'duty' => $assignDuty,
                'data' => $userList
            ]);
            if (!$exist)
                Client::send(RedisConstant::UpdateUserStatus, [
                    'taskType' => $taskType,
                    'taskSign' => $taskSign,
                ], strtotime(date('Y-m-d', time())) + 86400);
            if ($res) return json_encode(['msg' => '操作成功', 'code' => 200, 'data' => []]);
            return json_encode(['msg' => '操作失败', 'code' => 201, 'data' => []]);
        } catch (\Exception $e) {
            return json_encode(['msg' => $e->getMessage(), 'code' => 204, 'data' => []]);
        }
    }

    /**
     * 获取派发设置
     * @param array $args
     * @return string
     */
    public static function getTaskSetting(array $args): string
    {
        try {
            $taskType = $args['taskType'] ?? 'assign'; //任务类型、标识
            $taskSign = $args['taskSign'] ?? '1'; //分派名称、标识、ID
            $taskSetting = RedisConstant::TaskPrefix . $taskType . ':task:' . $taskSign;
            $data = RedisTool::get_forever($taskSetting, 'config');
            if (!$data) return json_encode(['msg' => '未配置此任务', 'code' => 201, 'data' => []]);
            return json_encode(['msg' => '操作成功', 'code' => 200, 'data' => $data]);
        } catch (\Exception $e) {
            return json_encode(['msg' => $e->getMessage(), 'code' => 204, 'data' => []]);
        }
    }

    /**
     * 配置派发用户
     * @param array $args
     * @return string
     */
    public static function setTaskUserList(array $args): string
    {
        try {
            $taskType = $args['taskType'] ?? 'assign'; //任务类型、标识
            $taskSign = $args['taskSign'] ?? '1'; //分派名称、标识、ID
            $userList = $args['userList'] ?? []; // 派发的用户列表 [['user_id'=>1,'in_queue'=>1,'weight'=>1,'username'=>'username','is_regular'=>0,'is_rest'=>0,'is_duty'=>0,'long_duty'=>0,'receive_times'=>0,'duty_times'=>0,'is_appoint'=>0]] user_id:用户ID,in_queue:是否参与派发,weight：分配权重,username:用户名称,is_regular：派发额外固定第一个,is_rest：是否休息,is_duty:是否值班,long_duty:长期值班,receive_times:可领取次数，若未0则表示不限制,duty_times:值班可领取次数，若未0则表示不限制 is_appoint:指定人，可多人

            //获取配置内容
            $redisKey = RedisConstant::TaskPrefix . $taskType . ':task:' . $taskSign;
            $setting = RedisTool::get_forever($redisKey, 'config');
            if (!$setting) throw new \Exception('请先配置派发设置');
            //异步处理派发人
            Client::send(RedisConstant::TaskUserList, [
                'name' => RedisConstant::TaskPrefix . $taskType . ':user:',
                'sign' => $taskSign,
                'mode' => $setting['assignMode'],
                'duty' => $setting['assignDuty'],
                'data' => $userList
            ]);
            return json_encode(['msg' => '操作成功', 'code' => 200, 'data' => []]);
        } catch (\Exception $e) {
            return json_encode(['msg' => $e->getMessage(), 'code' => 204, 'data' => []]);
        }
    }

    /**
     * 获取派发用户
     * @param array $args
     * @return string
     */
    public static function getTaskUserList(array $args): string
    {
        try {
            $taskType = $args['taskType'] ?? 'assign'; //任务类型、标识
            $taskSign = $args['taskSign'] ?? '1'; //分派名称、标识、ID
            $taskSetting = RedisConstant::TaskPrefix . $taskType . ':task:' . $taskSign;
            $setting = RedisTool::get_forever($taskSetting, 'config');
            if (!$setting) throw new \Exception('请先配置派发设置');
            $redisKey = RedisConstant::TaskPrefix . $taskType . ':user:' . RedisConstant::TaskAssignNormal . $taskSign;
            $data = [];
            if (in_array($setting['assignMode'], [1, 2])) {
                $data['normal'] = RedisTool::get_lRange($redisKey, 0, -1, 'list'); // 分配列表
            } elseif ($setting['assignMode'] == 3) {
                $data['normal'] = RedisTool::get_zSet_desc($redisKey, 0, 1, 'list');
            } else {
                $data['normal'] = RedisTool::get_zSet_asc($redisKey, 0, -1, 'list');
            }
            if ($setting['assignDuty']) {
                $redisKey = RedisConstant::TaskPrefix . $taskType . ':user:' . RedisConstant::TaskAssignDuty . $taskSign;;
                $data['duty'] = RedisTool::get_lRange($redisKey, 0, -1, 'list');
            }
            return json_encode(['msg' => '操作成功', 'code' => 200, 'data' => $data]);
        } catch (\Exception $e) {
            return json_encode(['msg' => $e->getMessage(), 'code' => 204, 'data' => []]);
        }
    }

    /**
     * 任务派发投递
     * @param array $args
     * @return string
     */
    public static function doAssignTask(array $args): string
    {
        try {
            $taskType = $args['taskType'] ?? 'assign'; //任务类型、标识
            $taskSign = $args['taskSign'] ?? '1'; //分派名称、标识、ID
            $data = $args['data'] ?? [];//分配的数据
            $taskSetting = RedisConstant::TaskPrefix . $taskType . ':task:' . $taskSign;
            $setting = RedisTool::get_forever($taskSetting, 'config');
            if (!$setting) throw new \Exception('请先配置派发设置');
            Client::send(RedisConstant::AssignTaskList, ['taskType' => $taskType, 'taskSign' => $taskSign, 'info' => $data]);
            return json_encode(['msg' => '操作成功', 'code' => 200, 'data' => []]);
        } catch (\Exception $e) {
            return json_encode(['msg' => $e->getMessage(), 'code' => 204, 'data' => []]);
        }
    }

    /**
     * 任务领取回执
     * @param array $args
     * @return string
     */
    public static function receiveAssignTask(array $args): string
    {
        try {
            $taskType = $args['taskType'] ?? 'assign'; //任务类型、标识
            $taskSign = $args['taskSign'] ?? '1'; //分派名称、标识、ID
            $data = $args['data'] ?? [];//分配的数据
            $taskSetting = RedisConstant::TaskPrefix . $taskType . ':task:' . $taskSign;
            $setting = RedisTool::get_forever($taskSetting, 'config');
            if (!$setting) throw new \Exception('请先配置派发设置');
            if (!isset($data['id']) || !$data['id']) throw new \Exception('领取参数错误');
            RedisTool::set_time(RedisConstant::TaskPrefix . $taskType . ':task:' . $taskSign . ':' . RedisConstant::TaskReceiveStatus . $data['id'], 1, 86400, 'list');
            return json_encode(['msg' => '操作成功', 'code' => 200, 'data' => []]);
        } catch (\Exception $e) {
            return json_encode(['msg' => $e->getMessage(), 'code' => 204, 'data' => []]);
        }
    }

    /**
     * 设置任务补发
     * @param array $args
     * @return string
     */
    public static function setTaskReissue(array $args): string
    {
        try {
            $taskType = $args['taskType'] ?? 'assign'; //任务类型、标识
            $taskSign = $args['taskSign'] ?? '1'; //分派名称、标识、ID
            $userInfo = $args['userInfo'] ?? []; //补发的用户资料
            $taskSetting = RedisConstant::TaskPrefix . $taskType . ':task:' . $taskSign;
            $setting = RedisTool::get_forever($taskSetting, 'config');
            if (!$setting) throw new \Exception('请先配置派发设置');
            if (!isset($userInfo['user_id']) || !$userInfo['user_id']) throw new \Exception('用户参数错误');

            //如果处于值班期间则补充至值班
            $inDutyTime = false;
            if ($setting['assignDuty'] && $setting['dutyTime']) {
                foreach ($setting['dutyTime'] as $dutyTime) {
                    list($begin, $end) = explode('-', $dutyTime);
                    $begin = strtotime(date('Y-m-d') . ' ' . $begin);
                    $end = strtotime(date('Y-m-d') . ' ' . $end);
                    if ($begin >= $end) {
                        $end = $end + 86400;
                    }
                    if (time() > $begin && time() < $end) $inDutyTime = true;
                }
            }
            if ($inDutyTime) {
                $redisKey = RedisConstant::TaskPrefix . $taskType . ':user:' . RedisConstant::TaskAssignDuty . $taskSign;
                RedisTool::set_lPush($redisKey, array_merge($userInfo, ['assign_mode' => 99, 'in_assign' => 1]), 'list');
            } else {
                $redisKey = RedisConstant::TaskPrefix . $taskType . ':user:' . RedisConstant::TaskAssignNormal . $taskSign;
                if (in_array($setting['assignMode'], [1, 2])) {
                    RedisTool::set_lPush($redisKey, array_merge($userInfo, ['assign_mode' => 99, 'in_assign' => 1]), 'list');
                } elseif ($setting['assignMode'] == 3) {
                    RedisTool::set_zAdd($redisKey, array_merge($userInfo, ['assign_mode' => 99, 'in_assign' => 1]), time(), 'list');
                } else {
                    RedisTool::set_zAdd($redisKey, array_merge($userInfo, ['assign_mode' => 99, 'in_assign' => 1]), -1, 'list');
                }
            }
            return json_encode(['msg' => '操作成功', 'code' => 200, 'data' => []]);
        } catch (\Exception $e) {
            return json_encode(['msg' => $e->getMessage(), 'code' => 204, 'data' => []]);
        }
    }
}